﻿(*   Copyright 2011 Alexander Omelchuk
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *)

module REPL
open System
open System.Reflection
open Microsoft.FSharp.Text.Lexing

open Lisp
open Lexer
open Parser
open Eval

let parse text =
  let lexbuff = LexBuffer<char>.FromString(text)
  try
    Parser.parse Lexer.tokenize lexbuff
  with e ->
    let pos = lexbuff.EndPos 
    failwith (sprintf "Parsing error at %d:%d\n" pos.Line pos.Column )

initRootEnvironment ()

let processExpr = function
  | "" -> None
  | text ->
      (parse text |> compile).Compile().Invoke(
        GEnvironment.Instance :> IDynamicEnvironment)
          |> toStr |> Some

let rec readAndProcess() =
    printf "> "
    match
      (try processExpr (Console.ReadLine()) with
        | ex ->
          let ex = match ex with
                    | :? TargetInvocationException as x -> x.InnerException
                    | _ -> ex
          match ex with
          | EvalException(msg) -> Some msg
          | :? Throw as x -> Some(String.Format(noCatcherForTag, x.Tag))
          | _ -> Some (sprintf "%s\n%s" ex.Message ex.StackTrace)
      ) with
    | None -> ()
    | Some x -> printfn "  %s\n" x; readAndProcess()

readAndProcess()